#ifndef _STRING_HPP_
#define _STRING_HPP_

#include "config.hpp"
#include "macros.hpp"
#include "base.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/algorithm/string.hpp>

using namespace boost;
using namespace fctr;
using namespace log4cpp;

#define A(str) encode<EncodingT,ansi>(str)
#define C(str) encode<ansi,EncodingT>(str)

NAMESPACE_BEGIN(interp)

    template <class EncodingT>
    class String
    : public Base<EncodingT>
    {
	private:
		typename EncodingT::string_t m_value;
		
    public:
        // Constructor
        String();

        String(typename EncodingT::string_t const& value);

        String(typename EncodingT::char_t const& value);

        FACTORY_PROTOTYPE1(String, In< shared_ptr< Base<EncodingT> > >)
        String(shared_ptr< Base<EncodingT> > const& value);

        // Destructor
        ~String();

        // Accessors
		typename EncodingT::string_t const& getValue() const;
        void setValue(typename EncodingT::string_t const& value);

        // Virtual methods
        virtual typename EncodingT::string_t toString() const;
        virtual shared_ptr< Base<EncodingT> > clone() const;
        virtual typename EncodingT::string_t getClassName() const;
        virtual shared_ptr< Base<EncodingT> > invoke(const typename EncodingT::string_t& method, std::vector< shared_ptr< Base<EncodingT> > >& params);
        
        // Dynamic methods
        FACTORY_PROTOTYPE1(concat, In< shared_ptr< Base<EncodingT> > >)
        shared_ptr< Base<EncodingT> > concat(shared_ptr< Base<EncodingT> > const& val) const;

        FACTORY_PROTOTYPE1(equals, In< shared_ptr< Base<EncodingT> > >)
        shared_ptr< Base<EncodingT> > equals(shared_ptr< Base<EncodingT> > const& val) const;

        FACTORY_PROTOTYPE1(notEquals, In< shared_ptr< Base<EncodingT> > >)
        shared_ptr< Base<EncodingT> > notEquals(shared_ptr< Base<EncodingT> > const& val) const;

        // Methods registration
        FACTORY_BEGIN_REGISTER
            CLASS_REGISTER    (String)
            CLASS_REGISTER1   (String)
            METHOD_REGISTER1  (String, shared_ptr< Base<EncodingT> >, concat, const_t)
            METHOD_REGISTER1  (String, shared_ptr< Base<EncodingT> >, equals, const_t)
            METHOD_REGISTER1  (String, shared_ptr< Base<EncodingT> >, notEquals, const_t)
        FACTORY_END_REGISTER

        // Methods unregistration
        FACTORY_BEGIN_UNREGISTER
            CLASS_UNREGISTER  (String)
            CLASS_UNREGISTER1 (String)
            METHOD_UNREGISTER1(String, concat)
            METHOD_UNREGISTER1(String, equals)
            METHOD_UNREGISTER1(String, notEquals)
        FACTORY_END_UNREGISTER
    };

    template <class EncodingT>
    bool check_string(shared_ptr< Base<EncodingT> > const& val, typename EncodingT::string_t& n);

    template <class EncodingT>
    bool check_char(shared_ptr< Base<EncodingT> > const& val, typename EncodingT::char_t& n);

NAMESPACE_END

#include "string_impl.hpp"

#undef C
#undef A

#endif